﻿using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using WeChatSDK.Common;
using WeChatSDK.Common.Enums.Http;
using WeChatSDK.RequestComponent.Http;
using WeChatSDK.WeChatDto.MP;
using WeChatSDK.WeChatDto.Request.Http;
using WeChatSDK.WeChatServiceComponent.Conversation.BaseSupport;

namespace WeChatSDK.WeChatServiceComponent.News.News
{
    /// <summary>
    /// 微信群发功能服务
    /// </summary>
    public class MPService
    {
        private readonly HttpHandle httpHandle;
        public MPService()
        {
            this.httpHandle = new HttpHandle();
        }
        #region 查询群发消息发送状态
        /// <summary>
        /// 查询群发消息发送状态
        /// </summary>
        /// <param name="msgId">消息Id</param>
        /// <returns>{"msg_id":201053012,"msg_status":"SEND_SUCCESS"}
        /// msg_status	消息发送后的状态，SEND_SUCCESS表示发送成功，SENDING表示发送中，SEND_FAIL表示发送失败，DELETE表示已删除
        /// </returns>
        public HttpResponseDto Status(string msgId)
        {
            //微信图片上传得用WebClient，不可以使用HttpClient
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/message/mass/get?access_token={0}", new BaseSupportService().CreateAccessToken().AccessToken);
            dynamic dto = new { MsgId = msgId };
            return SendRequest(url, dto);
        }
        #endregion

        #region 预览群发消息
        /// <summary>
        /// 开发者可通过该接口发送消息给指定用户，在手机端查看消息的样式和排版。
        /// 为了满足第三方平台开发者的需求，在保留对openID预览能力的同时，
        /// 增加了对指定微信号发送预览的能力，但该能力每日调用次数有限制（100次），请勿滥用。
        /// </summary>
        /// <param name="openId">OpenId</param>
        /// <param name="towxname">微信号,微信号存在时，优先微信号发送预览</param>
        /// <param name="mpDto">群发消息</param>
        /// <returns>{ "errcode":0,"errmsg":"preview success","msg_id":34182}</returns>
        public HttpResponseDto Preview<T>(string openId, string towxname, T mpDto) where T : IMPTouserPreviewConstraint
        {
            //微信图片上传得用WebClient，不可以使用HttpClient
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token={0}", new BaseSupportService().CreateAccessToken().AccessToken);
            dynamic dto = mpDto;
            dto.Touser = openId;
            if (!string.IsNullOrWhiteSpace(towxname))
            {
                dto.Towxname = towxname;
            }
            return SendRequest(url, dto);
        }
        #endregion

        #region 删除群发消息
        /// <summary>
        /// 删除群发消息
        /// 1、只有已经发送成功的消息才能删除
        /// 2、删除消息是将消息的图文详情页失效，已经收到的用户，还是能在其本地看到消息卡片。
        /// 3、删除群发消息只能删除图文消息和视频消息，其他类型的消息一经发送，无法删除。
        /// 4、如果多次群发发送的是一个图文消息，那么删除其中一次群发，就会删除掉这个图文消息，也会导致所有群发都失效
        /// </summary>
        /// <param name="msgId">消息Id</param>
        /// <param name="articleIdx">要删除的文章在图文消息中的位置，第一篇编号为1，该字段不填或填0会删除全部文章</param>
        /// <returns>{ "errcode":0,"errmsg":"ok"}</returns>
        public HttpResponseDto Delete(long msgId, int? articleIdx)
        {
            //微信图片上传得用WebClient，不可以使用HttpClient
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/message/mass/delete?access_token={0}", new BaseSupportService().CreateAccessToken().AccessToken);
            object obj = new { MsgId = msgId, ArticleIdx = articleIdx };
            return SendRequest(url, obj);
        }
        #endregion

        #region 群发消息
        /// <summary>
        /// 群发消息
        /// </summary>
        /// <param name="mpDto">群发信息</param>
        /// <returns>
        /// {
        /// "type":"news"   //媒体文件类型，分别有图片（image）、语音（voice）、视频（video）和缩略图（thumb），图文消息为news
        /// "errcode":0,    //错误码
        /// "errmsg":"send job submission success", //	错误信息
        /// "msg_id":34182,     //消息发送任务的ID
        /// "msg_data_id": 206227730    //消息的数据ID，该字段只有在群发图文消息时，才会出现。可以用于在图文分析数据接口中，获取到对应的图文消息的数据，是图文分析数据接口中的msgid字段中的前半部分，详见图文分析数据接口中的msgid字段的介绍。
        /// }
        /// </returns>
        public HttpResponseDto Send<T>(T mpDto) where T : MPDto
        {
            if (mpDto.Msgtype == "mpvideo")
            {
                throw new WeChatException("微信视频群发请使用MPSend方法。");
            }
            return SendMPNews(mpDto);
        }
        /// <summary>
        /// 群发消息
        /// </summary>
        /// <param name="mpDto">群发信息</param>
        /// <param name="title">视频消息群发标题，仅在视频消息群发时需要</param>
        /// <param name="description">视频消息描述，仅在视频消息群发时需要</param>
        /// <returns>
        /// {
        /// "type":"news"   //媒体文件类型，分别有图片（image）、语音（voice）、视频（video）和缩略图（thumb），图文消息为news
        /// "errcode":0,    //错误码
        /// "errmsg":"send job submission success", //	错误信息
        /// "msg_id":34182,     //消息发送任务的ID
        /// "msg_data_id": 206227730    //消息的数据ID，该字段只有在群发图文消息时，才会出现。可以用于在图文分析数据接口中，获取到对应的图文消息的数据，是图文分析数据接口中的msgid字段中的前半部分，详见图文分析数据接口中的msgid字段的介绍。
        /// }
        /// </returns>
        public HttpResponseDto MPSend<T>(T mpDto, string title, string description) where T : MPDto
        {
            if (mpDto.Msgtype == "mpvideo")
            {
                MPVideoDto mPVideoDto = mpDto as MPVideoDto;
                ///微信调整了群发视频，无需再次调用兑换新视频素材Id
                //string response = ExchangeVideoMediaId(new { MediaId = mPVideoDto.Mpvideo.MediaId, Type = title, Description = description }).ResponseMessage;
                //if (response.IndexOf("{")<0) {
                //    throw new WeChatException(response);
                //}
                //dynamic result = JsonConvert.DeserializeObject<dynamic>(response);
                //mPVideoDto.Mpvideo.MediaId = result.media_id;
                mpDto = mPVideoDto as T;
            }
            return SendMPNews(mpDto);
        }

        private HttpResponseDto SendMPNews<T>(T mpDto) where T : MPDto
        {
            //微信图片上传得用WebClient，不可以使用HttpClient
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token={0}", new BaseSupportService().CreateAccessToken().AccessToken);
            return SendRequest(url, mpDto);
        }

        private HttpResponseDto ExchangeVideoMediaId(object obj)
        {
            //微信图片上传得用WebClient，不可以使用HttpClient
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/media/uploadvideo?access_token={0}", new BaseSupportService().CreateAccessToken().AccessToken);
            return SendRequest(url, obj);
        }
        #endregion

        #region 已群发文章评论
        /// <summary>
        /// 打开已群发文章评论
        /// </summary>
        /// <param name="messageDataId">群发返回的msg_data_id</param>
        /// <param name="index">第几篇图文，从0开始</param>
        /// <returns>{ "errcode": ERRCODE, "errmsg" : ERRMSG }</returns>
        public HttpResponseDto OpenNeedComment(long messageDataId, int index)
        {
            //微信图片上传得用WebClient，不可以使用HttpClient
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/comment/open?access_token={0}", new BaseSupportService().CreateAccessToken().AccessToken);
            return SendRequest(url, new { MsgDataId = messageDataId, Index = index });
        }

        /// <summary>
        /// 关闭已群发文章评论
        /// </summary>
        /// <param name="messageDataId">群发返回的msg_data_id</param>
        /// <param name="index">第几篇图文，从0开始</param>
        /// <returns>{ "errcode": ERRCODE, "errmsg" : ERRMSG }</returns>
        public HttpResponseDto CloseNeedComment(long messageDataId, int index)
        {
            //微信图片上传得用WebClient，不可以使用HttpClient
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/comment/close?access_token={0}", new BaseSupportService().CreateAccessToken().AccessToken);
            return SendRequest(url, new { MsgDataId = messageDataId, Index = index });
        }

        /// <summary>
        /// 查看已群发文章评论
        /// </summary>
        /// <param name="messageDataId">群发返回的msg_data_id</param>
        /// <param name="index">第几篇图文，从0开始</param>
        /// <param name="begin">起始位置</param>
        /// <param name="count">获取数目,应小于50，大于50会被拒绝</param>
        /// <param name="type">type=0 普通评论&精选评论 type=1 普通评论 type=2 精选评论</param>
        /// <returns>
        /// {
        ///  "errcode": 0,
        ///	    "errmsg": "ok",
        ///	    "total": TOTAL //总数，非comment的size
        ///	    "comment": [{
        ///        user_comment_id: USER_COMMENT_ID //用户评论id 
        ///        aroundopenid: OPENID //openid 
        ///        aroundcreate_time: CREATE_TIME //评论时间 
        ///        aroundcontent: CONTENT //评论内容
        ///        aroundcomment_type: IS_ELECTED //是否精选评论，0为即非精选，1为true，即精选around 
        ///        reply: {
        ///            content: CONTENT //作者回复内容around 
        ///            create_time: CREATE_TIME //作者回复时间 
        ///        }
        ///     }]
        /// }
        /// </returns>
        public HttpResponseDto GetNeedCommentList(long messageDataId, int index, long begin, long count, int type = 0)
        {
            //微信图片上传得用WebClient，不可以使用HttpClient
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/comment/list?access_token={0}", new BaseSupportService().CreateAccessToken().AccessToken);
            return SendRequest(url, new { MsgDataId = messageDataId, Index = index, Begin = begin, Count = count, Type = type });
        }
        /// <summary>
        /// 将评论标记精选
        /// </summary>
        /// <param name="messageDataId">消息数据Id</param>
        /// <param name="index">第几篇图文，从0开始</param>
        /// <param name="userCommentId">用户评论Id</param>
        /// <returns>{ "errcode": ERRCODE, "errmsg" : ERRMSG }</returns>
        public HttpResponseDto MarkChoice(long messageDataId, int index, long userCommentId)
        {
            //微信图片上传得用WebClient，不可以使用HttpClient
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/comment/markelect?access_token={0}", new BaseSupportService().CreateAccessToken().AccessToken);
            return SendRequest(url, new { MsgDataId = messageDataId, Index = index, UserCommentId=userCommentId });
        }
        /// <summary>
        /// 取消标记用户评论为精选
        /// </summary>
        /// <param name="messageDataId">消息数据Id</param>
        /// <param name="index">第几篇图文，从0开始</param>
        /// <param name="userCommentId">用户评论Id</param>
        /// <returns>{ "errcode": ERRCODE, "errmsg" : ERRMSG }</returns>
        public HttpResponseDto UnMarkChoice(long messageDataId, int index, long userCommentId)
        {
            //微信图片上传得用WebClient，不可以使用HttpClient
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/comment/unmarkelect?access_token={0}", new BaseSupportService().CreateAccessToken().AccessToken);
            return SendRequest(url, new { MsgDataId = messageDataId, Index = index, UserCommentId = userCommentId });
        }
        /// <summary>
        /// 删除用户评论
        /// </summary>
        /// <param name="messageDataId">消息数据Id</param>
        /// <param name="index">第几篇图文，从0开始</param>
        /// <param name="userCommentId">用户评论Id</param>
        /// <returns>{ "errcode": ERRCODE, "errmsg" : ERRMSG }</returns>
        public HttpResponseDto DeleteUserComment(long messageDataId, int index, long userCommentId)
        {
            //微信图片上传得用WebClient，不可以使用HttpClient
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/comment/delete?access_token={0}", new BaseSupportService().CreateAccessToken().AccessToken);
            return SendRequest(url, new { MsgDataId = messageDataId, Index = index, UserCommentId = userCommentId });
        }
        /// <summary>
        /// 回复用户评论
        /// </summary>
        /// <param name="messageDataId">消息数据Id</param>
        /// <param name="index">第几篇图文，从0开始</param>
        /// <param name="userCommentId">用户评论Id</param>
        /// <param name="content">回复内容</param>
        /// <returns>{ "errcode": ERRCODE, "errmsg" : ERRMSG }</returns>
        public HttpResponseDto ReplyUserComment(long messageDataId, int index, long userCommentId,string content)
        {
            //微信图片上传得用WebClient，不可以使用HttpClient
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/comment/reply/add?access_token={0}", new BaseSupportService().CreateAccessToken().AccessToken);
            return SendRequest(url, new { MsgDataId = messageDataId, Index = index, UserCommentId = userCommentId });
        }
        /// <summary>
        /// 删除回复用户评论
        /// </summary>
        /// <param name="messageDataId">消息数据Id</param>
        /// <param name="index">第几篇图文，从0开始</param>
        /// <param name="userCommentId">用户评论Id</param>
        /// <returns>{ "errcode": ERRCODE, "errmsg" : ERRMSG }</returns>
        public HttpResponseDto DeleteReplyUserComment(long messageDataId, int index, long userCommentId)
        {
            //微信图片上传得用WebClient，不可以使用HttpClient
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/comment/reply/delete?access_token={0}", new BaseSupportService().CreateAccessToken().AccessToken);
            return SendRequest(url, new { MsgDataId = messageDataId, Index = index, UserCommentId = userCommentId });
        }
        #endregion



        #region 执行发送消息
        /// <summary>
        /// 执行发送消息
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="obj">对象信息</param>
        /// <returns></returns>
        private HttpResponseDto SendRequest(string url, object obj)
        {
            HttpRequestDto httpRequestDto = new HttpRequestDto();
            httpRequestDto.Url = url;
            httpRequestDto.Headers.Add("Content-Type", "application/json");
            httpRequestDto.Content = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(obj, WeChatGeneral.JsonSerializerSettings));
            httpRequestDto.Method = MethodType.POST;
            httpRequestDto.ContentType = FormatType.JSON;
            return httpHandle.WebSendRequest(httpRequestDto);
        }
        #endregion
    }
}
